package com.xz.xzutils.module.xzmybatislogplus.extension;

import com.intellij.execution.RunConfigurationExtension;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.RunConfigurationBase;
import com.intellij.execution.configurations.RunnerSettings;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.extensions.PluginId;
import com.xz.xzutils.module.xzmybatislogplus.dto.SocketPort;
import com.xz.xzutils.settings.mybatislogplus.MybatisLogPlusPersistentState;
import com.xz.xzutils.settings.mybatislogplus.MybatisLogPlusState;
import com.xz.xzutils.utils.MyBatisDetector;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.nio.file.Path;
import java.util.Optional;

/**
 * <p>
 * 此扩展点的目的是执行java程序时检测是否使用了mybatis，如果使用了，则添加虚拟机代理程序
 * </p>
 *
 * @author DONG.WANG17@HAND-CHINA.COM
 * @since 2025-02-14 00:13
 */
@Slf4j
public class JvmArgsExtension extends RunConfigurationExtension {
    MybatisLogPlusState mybatisLogPlusState = MybatisLogPlusPersistentState.getInstance().getState();

    private static String getJarPath() {
        PluginId pluginId = PluginId.getId("com.xz.xzutils");
        IdeaPluginDescriptor plugin = PluginManagerCore.getPlugin(pluginId);
        if (plugin == null) {
            return null;
        }
        Path pluginPath = plugin.getPluginPath();
        // TODO 优化
        return pluginPath.toAbsolutePath() + "\\lib\\xz-mybatis-agent.jar";
    }

    @Override
    public <T extends RunConfigurationBase<?>> void updateJavaParameters(@NotNull T t, @NotNull JavaParameters javaParameters, @Nullable RunnerSettings runnerSettings) {
        log.info("位置：{}", JvmArgsExtension.class.getName());

        if (t.getProject().getUserData(SocketPort.SOCKET_PORT_ENTITY) == null) {
            SocketPort socketPort = new SocketPort();
            socketPort.setMinPort(mybatisLogPlusState.getMinPort());
            socketPort.setMaxPort(mybatisLogPlusState.getMaxPort());
            t.getProject().putUserData(SocketPort.SOCKET_PORT_ENTITY, socketPort);
        }
        SocketPort socketPort = t.getProject().getUserData(SocketPort.SOCKET_PORT_ENTITY);
        if (socketPort == null) return;

        int sqlPort = socketPort.getRandomPort();
        int activePort = socketPort.getRandomPort();
        // TODO 如果 MyExecutionListener 没有及时消费端口，这里覆盖后，MyExecutionListener 可能会获取到错误端口
        t.getProject().putUserData(SocketPort.SOCKET_PORT, sqlPort);

        String jarPath = getJarPath();
        String agentParameter = String.format("-javaagent:%s=sqlPort=%s,activePort=%s", jarPath, sqlPort, activePort);


        Optional<String> findAny = javaParameters.getVMParametersList().getParameters().stream().filter(agentParameter::equals).findAny();
        if (findAny.isPresent()) {
            // 已经添加过代理参数[{}]，不执行任何操作
            return;
        }
        // 添加 jvm 参数
        // log.info("添加代理参数[{}]", agentParameter);
        javaParameters.getVMParametersList().add(agentParameter);
        // 允许 attach
        javaParameters.getVMParametersList().add("-Djdk.attach.allowAttachSelf=true");
    }

    @Override
    public boolean isApplicableFor(@NotNull RunConfigurationBase<?> configuration) {
        // "使用了 mybatis,项目启动时添加虚拟机代理程序"
        return MyBatisDetector.hasMybatisDependency(configuration.getProject());
    }
}
